package tracex

import (
	"context"

	zeroTrace "github.com/zeromicro/go-zero/core/trace"
	"go.opentelemetry.io/otel/propagation"
	"go.opentelemetry.io/otel/sdk/resource"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
	semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
	"go.opentelemetry.io/otel/trace"
	otelTrace "go.opentelemetry.io/otel/trace"
)

var (
	globalTracerProvider    otelTrace.TracerProvider
	globalTextMapPropagator propagation.TextMapPropagator
)

func init() {
	c := zeroTrace.Config{
		Name: "tracex",
	}

	opts := []sdktrace.TracerProviderOption{
		// Set the sampling rate based on the parent span to 100%
		sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.TraceIDRatioBased(c.Sampler))),
		// Record information about this application in an Resource.
		sdktrace.WithResource(resource.NewSchemaless(semconv.ServiceNameKey.String(c.Name))),
	}

	globalTracerProvider = sdktrace.NewTracerProvider(opts...)

	globalTextMapPropagator = propagation.NewCompositeTextMapPropagator(
		propagation.TraceContext{}, propagation.Baggage{})
}

// AddTraceHeader header注入traceparent
func AddTraceHeader(ctx context.Context, header map[string][]string) (context.Context, string) {
	spanCtx := trace.SpanContextFromContext(ctx)
	if spanCtx.HasTraceID() { //存在则返回
		inject(ctx, header)
		return ctx, spanCtx.TraceID().String()
	} 
 
	tracer := globalTracerProvider.Tracer(zeroTrace.TraceName)
	newCtx, span := tracer.Start(ctx, "own", otelTrace.WithSpanKind(otelTrace.SpanKindServer))
	defer span.End()

	inject(newCtx, header)
	return newCtx, span.SpanContext().TraceID().String()
}

// AddTrace ctx中加入trace信息
func AddTrace(ctx context.Context) (context.Context, string) {
	spanCtx := trace.SpanContextFromContext(ctx)
	if spanCtx.HasTraceID() { //存在则返回
		return ctx, spanCtx.TraceID().String()
	}

	tracer := globalTracerProvider.Tracer(zeroTrace.TraceName)
	newCtx, span := tracer.Start(ctx, "own", otelTrace.WithSpanKind(otelTrace.SpanKindServer))
	defer span.End()

	return newCtx, span.SpanContext().TraceID().String()
}

func inject(ctx context.Context, carrier map[string][]string) {
	globalTextMapPropagator.Inject(ctx, propagation.HeaderCarrier(carrier))
}
